<?php
/*
Plugin Name: Achievements
Plugin URI: http://www.metabiscuits.com
Description: Brings Achievements (similar to World of Warcraft or Xbox Live) to BuddyPress.
Version: 1.0
Requires at least: WPMU 2.8.2, BuddyPress 1.0.3
Tested up to: WPMU 2.8.3, BuddyPress rev 1634
License: General Public License version 3 
Author: Paul Gibbs
Author URI: http://www.twitter.com/pgibbs
Site Wide Only: true


"Achievements" for BuddyPress
Copyright (C) 2009 Paul Gibbs

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3 as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see http://www.gnu.org/licenses/.


This software uses icons from the FAMFAMFAM "Silk" icon set used under
the http://creativecommons.org/licenses/by/3.0/ license (achievements_bullet.png,
cross.png, tick.png).
Visit them at http://www.famfamfam.com/lab/icons/silk/; thank you!


For developer documentation, please see devdoc.txt.
*/
define( 'DPA_IS_INSTALLED', 1 );
define( 'DPA_VERSION', '1.0' );
define( 'DPA_DB_VERSION', '6' );
define( 'DPA_REGISTERFUNCTION', 'dpa_register_' );

if ( !defined( 'DPA_SLUG' ) )
	define( 'DPA_SLUG', apply_filters( 'dpa_slug', 'achievements' ) );

require_once( 'dp-achievements/dp-achievements-classes.php' );
require_once( 'dp-achievements/dp-achievements-filters.php' );
require_once( 'dp-achievements/dp-achievements-templatetags.php' );
require_once( 'dp-achievements/dp-achievements-defaultachievements.php' );
require_once( 'dp-achievements/dp-achievements-notifications.php' );
require_once( 'dp-achievements/dp-achievements-cssjs.php' );
require_once( 'dp-achievements/dp-achievements-admin.php' );


/*
 * BP component implementation
 */
function dpa_load_buddypress() {
	if ( function_exists( 'bp_core_setup_globals' ) )
		return true;
	
	/* Get the list of active sitewide plugins */
	$active_sitewide_plugins = maybe_unserialize( get_site_option( 'active_sitewide_plugins' ) );
	if ( isset( $active_sidewide_plugins['buddypress/bp-loader.php'] ) && !function_exists( 'bp_core_setup_globals' ) ) {
		require_once( WP_PLUGIN_DIR . '/buddypress/bp-loader.php' );
		return true;
	}
	
	/* If we get to here, BuddyPress is not active, so we need to deactive the plugin and redirect. */
	require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
	if ( file_exists( ABSPATH . 'wp-admin/includes/mu.php' ) )
		require_once( ABSPATH . 'wp-admin/includes/mu.php' );

	deactivate_plugins( basename( __FILE__ ), true );
	if ( function_exists( 'deactivate_sitewide_plugin' ) )
		deactivate_sitewide_plugin( basename( __FILE__ ), true );
		
	wp_redirect( get_blog_option( BP_ROOT_BLOG, 'home' ) . '/wp-admin/plugins.php' );
}
add_action( 'plugins_loaded', 'dpa_load_buddypress', 5 );

function dpa_check_installed() {	
	global $wpdb, $bp;

	if ( !is_site_admin() )
		return false;

	/* Need to check db tables exist, activate hook no-worky in mu-plugins folder. */
	if ( get_site_option( 'dpa_db_version' ) < DPA_DB_VERSION )
		dpa_install();
}
add_action( 'admin_menu', 'dpa_check_installed', 1 );

function dpa_load_textdomain() {
	$locale = apply_filters( 'buddypress_locale', get_locale() );
	$mofile = WP_PLUGIN_DIR . "/achievements/dp-achievements/languages/achievements-$locale.mo";

	if ( file_exists( $mofile ) )
		load_textdomain( 'dp-achievements', $mofile );
}
add_action ( 'plugins_loaded', 'dpa_load_textdomain', 7 );

function dpa_install() {
	global $wpdb, $bp;

	if ( !empty( $wpdb->charset ) )
		$charset_collate = "DEFAULT CHARACTER SET $wpdb->charset";

	$sql = array();
	$sql[] = "CREATE TABLE {$bp->achievements->table_name} (
					id bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
					category_id bigint(20) NOT NULL,
					short_name varchar(100) NOT NULL,
					nice_name varchar(100) NOT NULL,
					description longtext NOT NULL,
					points int(100) NOT NULL,
					active int(1) NOT NULL,
					KEY short_name (short_name)
				 ) {$charset_collate};";
	$sql[] = "CREATE TABLE {$bp->achievements->table_name_unlocked} (
					id bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
					achievement_id bigint(20) NOT NULL,
				  user_id bigint(20) NOT NULL,
					achieved_at DATETIME NOT NULL
				 ) {$charset_collate};";
	$sql[] = "CREATE TABLE {$bp->achievements->table_name_categories} (
				 id bigint(20) NOT NULL AUTO_INCREMENT PRIMARY KEY,
				 category varchar(100) NOT NULL
				 ) {$charset_collate};";

	$categories = dpa_get_defaultcategories();
	foreach( (array) $categories as $c ) {
		$sql[] = $wpdb->prepare( "INSERT INTO {$bp->achievements->table_name_categories} ( category ) VALUES ( %s );", $c );
	}

	require_once( ABSPATH . 'wp-admin/upgrade-functions.php' );
	dbDelta( $sql );
	$sql = array();

	$achievements = dpa_get_defaultachievements();
	foreach ( (array) $achievements as $a ) {
		$category_id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$bp->achievements->table_name_categories} WHERE category = %s", $a['category'] ) );

		$sql[] = $wpdb->prepare( "INSERT INTO {$bp->achievements->table_name} ( category_id, short_name, nice_name, description, points, active ) VALUES ( %d, %s, %s, %s, %d, %d );", $category_id, $a['short_name'], $a['name'], $a['description'], $a['points'], 1 );
	}
	dbDelta( $sql );

	update_site_option( 'dpa_db_version', DPA_DB_VERSION );
}

function dpa_setup_globals() {
	global $bp, $wpdb;
	
	$bp->achievements->table_name = $wpdb->base_prefix . 'dpa_achievements';
	$bp->achievements->table_name_unlocked = $wpdb->base_prefix . 'dpa_achievements_unlocked';
	$bp->achievements->table_name_categories = $wpdb->base_prefix . 'dpa_achievements_categories';
	$bp->achievements->image_base = WP_PLUGIN_URL . '/dp-achievements/images';
	$bp->achievements->format_activity_function = 'dpa_format_activity';
	$bp->achievements->format_notification_function = 'dpa_format_notifications';
	$bp->achievements->slug = DPA_SLUG;

	$bp->version_numbers->dp_achievements = DPA_VERSION;
}
add_action( 'plugins_loaded', 'dpa_setup_globals', 6 );	
add_action( 'admin_menu', 'dpa_setup_globals', 1 );

function dpa_setup_nav() {
	global $bp;

	if ( false === get_site_option( 'dpa_db_version' ) )
		return;

 	bp_core_add_nav_item( __( 'Achievements', 'dp-achievements' ), $bp->achievements->slug );
	bp_core_add_nav_default( $bp->achievements->slug, 'dpa_screen_index', apply_filters( 'dpa_screen_summary_slug', 'summary' ) );

	$achievements_link = $bp->loggedin_user->domain . $bp->achievements->slug . '/';
	bp_core_add_subnav_item( $bp->achievements->slug, apply_filters( 'dpa_screen_summary_slug', 'summary' ), __( 'Summary', 'dp-achievements' ), $achievements_link, 'dpa_screen' );
	$categories = dpa_get( 'DISTINCT category', array( array( 'type' => 'd', 'key' => 'active', 'value' => 1 ) ) );

	foreach ( (array) $categories as $category_name ) {
		bp_core_add_subnav_item( $bp->achievements->slug, apply_filters( 'dpa_screen_summary_slug_url', __( $category_name, 'dp-achievements' ) ), __( $category_name, 'dp-achievements' ), $achievements_link, 'dpa_screen' );		
	}

	if ( $bp->current_component == $bp->achievements->slug ) {
		if ( bp_is_home() ) {
			$bp->bp_options_title = __( 'Category', 'dp-achievements' );
		} else {
			$bp->bp_options_avatar = bp_core_get_avatar( $bp->displayed_user->id, 1 );
			$bp->bp_options_title = __( 'Category', 'dp-achievements' );
		}
	}
}
add_action( 'wp', 'dpa_setup_nav', 2 );

/**
 * Based on bp_core_load_uri().
 */
function dpa_load_template( $pages ) {
	global $bp_path, $bp_skip_blog_check;
	
	$bp_skip_blog_check = false;
	$bp_path = $pages;

	remove_action( 'template_redirect', 'redirect_canonical' );
	add_action( 'template_redirect', 'dpa_catch_uri', 2 );
}

/**
 * Avoids forcing people to move member-theme files after automatic install (unless they want to customise the pages).
 * Based on bp_core_do_catch_uri().
 */
function dpa_catch_uri() {
	global $bp_path, $bp, $wpdb;
	global $current_blog, $bp_skip_blog_check;
	global $bp_no_status_set;
	global $wp_query;
	
	$page = $bp_path;

	/* Make sure this is not reported as a 404 */
	if ( !$bp_no_status_set ) {
		status_header( 200 );
		$wp_query->is_404 = false;
		
		if ( $bp->current_component != BP_HOME_BLOG_SLUG )
			$wp_query->is_page = true;
	}

	if ( file_exists( TEMPLATEPATH . "/" . $page . ".php" ) ) {
		bp_core_do_catch_uri();
	} else {

	  $page = strrchr( $page, '/' );
		if ( file_exists( WP_PLUGIN_DIR . '/achievements/dp-achievements/achievements-member-theme/' . $page . ".php" ) ) {
			load_template( WP_PLUGIN_DIR . '/achievements/dp-achievements/achievements-member-theme/' . $page . ".php" );
		} else {

			if ( file_exists( TEMPLATEPATH . "/404.php" ) ) {
				status_header( 404 );
				load_template( TEMPLATEPATH . "/404.php" );
			} else {

				wp_die( __( '<strong>You do not have the Achievements plugin installed correctly.</strong><br />Please remove the files and try again.', 'dp-achievements' ) );
			}
		}
	}
	
	die;
}

function dpa_screen() {
	$page = esc_attr__( bp_current_action() );

	if ( $page == 'summary' ) {
		do_action( 'dpa_screen_summary' );
 		dpa_load_template( apply_filters( 'dpa_screen_summarypage', 'achievements/summary' ) );
  } else {
		do_action( 'dpa_screen_category', $page );
		dpa_load_template( apply_filters( 'dpa_screen_categorypage', 'achievements/category' ) );
	}
}

function dpa_load_achievements() {
	if ( false === get_site_option( 'dpa_db_version' ) )
		return;

	$achievements = dpa_get( 'short_name', array( array( 'type' => 'd', 'key' => 'active', 'value' => 1 ) ) );	
	$unique_achievements = array();

  // Strips out anything after underscores (for ranked achievements).
	foreach ( (array) $achievements as $a ) { 
		$short_name = DPA_REGISTERFUNCTION . $a; 
		$i = strpos( $short_name, '_', strlen( DPA_REGISTERFUNCTION ) ); 
		if ( $i !== false )
			$short_name = substr( $short_name, 0, $i ); 

		$unique_achievements[] = $short_name; 
	}
	$unique_achievements = array_unique( $unique_achievements ); 

	foreach ( (array) $unique_achievements as $achievement ) {
		if ( function_exists( $achievement ) ) {
			do_action( 'dpa_preload_' . $achievement );
			call_user_func( $achievement );
			do_action( 'dpa_postload_' . $achievement );
		}
	}
}
add_action( 'plugins_loaded', 'dpa_load_achievements' );


/*
 * Activity
 */
function dpa_format_activity( $item_id, $user_id, $action, $secondary_item_id = false, $for_secondary_user = false ) {
	global $bp;
	
	switch( $action ) {
		case 'new_achievement':
			$user_link = bp_core_get_userlink( $user_id );
			$achievement_name = apply_filters( 'dpa_filter_achievement_nice_name', dpa_get( 'nice_name', array( array( 'type' => 'd', 'key' => 'id', 'value' => $item_id ) ), 1 ) );

			return array( 
				'primary_link' => $user_link,
				'content' => apply_filters( 'dpa_new_achievement_activity', sprintf( __( '%s unlocked achievement: %s', 'dpa-achievement' ), $user_link, $achievement_name ) . __( ' <span class="time-since">%s</span>', 'dpa-achievement' ), $user_id, $item_id )
			);				
		break;
	}
	
	do_action( 'dpa_format_activity', $action, $item_id, $user_id, $action, $secondary_item_id, $for_secondary_user );
	
	return false;
}

function dpa_record_activity( $args ) {
	if ( function_exists( 'bp_activity_record' ) ) {
		extract( (array) $args );
		bp_activity_record( $item_id, $component_name, $component_action, $is_private, $secondary_item_id, $user_id, $secondary_user_id, $recorded_time );
	}
}


/*
 * Notification
 */
function dpa_screen_notification_settings() { 
	global $current_user;
	?>
	<table class="notification-settings" id="achievements-notification-settings">
		<tr>
			<th class="icon"></th>
			<th class="title"><?php _e( 'Achievements', 'dp-achievements' ) ?></th>
			<th class="yes"><?php _e( 'Yes', 'dp-achievements' ) ?></th>
			<th class="no"><?php _e( 'No', 'dp-achievements' )?></th>
		</tr>
		<tr>
			<td></td>
			<td><?php _e( 'You unlock an achievement', 'dp-achievements' ) ?></td>
			<td class="yes"><input type="radio" name="notifications[notification_dpa_unlock_achievement]" value="yes" <?php if ( !get_usermeta( $current_user->id,'notification_dpa_unlock_achievement' ) || 'yes' == get_usermeta( $current_user->id,'notification_dpa_unlock_achievement' ) ) { ?>checked="checked" <?php } ?>/></td>
			<td class="no"><input type="radio" name="notifications[notification_dpa_unlock_achievement]" value="no" <?php if ( get_usermeta( $current_user->id,'notification_dpa_unlock_achievement' ) == 'no' ) { ?>checked="checked" <?php } ?>/></td>
		</tr>
		
		<?php do_action( 'dpa_screen_notification_settings' ); ?>
	</table>
<?php	
}
add_action( 'bp_notification_settings', 'dpa_screen_notification_settings' );

function dpa_format_notifications( $action, $item_id, $secondary_item_id, $total_items ) {
	global $bp;

	switch ( $action ) {
		case 'new_achievement':
			if ( $item_id ) {
				$achievement_name = apply_filters( 'dpa_filter_achievement_nice_name', dpa_get( 'nice_name', array( array( 'type' => 'd', 'key' => 'id', 'value' => $item_id ) ), 1 ) );
				$user_url = bp_core_get_userurl( $secondary_item_id );
				return apply_filters( 'dpa_new_achievement_notification', '<a href="' . $user_url . DPA_SLUG. '">' . sprintf( __( 'Achievement Unlocked: %s', 'dp-achievements' ), $achievement_name ) . '</a>', $secondary_item_id, $item_id );

			} else {
				$user_url = bp_core_get_userurl( $secondary_item_id );
				return apply_filters( 'dpa_new_achievement_notification', '<a href="' . $user_url . DPA_SLUG. '">' . __( 'Achievements Unlocked!', 'dp-achievements' ) . '</a>', $secondary_item_id, $item_id );
			}
		break;
	}

	do_action( 'dpa_format_notifications', $action, $item_id, $secondary_item_id, $total_items );

	return false;
}

function dpa_remove_notifications() {
	global $bp;

	bp_core_delete_notifications_for_user_by_type( $bp->loggedin_user->id, $bp->achievements->slug, 'new_achievement' );
}
add_action( 'dpa_screen_summary', 'dpa_remove_notifications' );
?>